<?php

namespace App\Libs\Xlsx;

use Exception;
use Vtiful\Kernel\Excel;
use Vtiful\Kernel\Format;

/**
 * `xlswriter` 导出
 * Class Export
 *
 * @package App\Libs\Xlsx
 * create_at: 2023-09-22 16:42:36
 * update_at: 2023-09-22 16:42:36
 */
class XlsWriter
{
    /**
     * 实例
     *
     * @var null
     * create_at: 2023-09-22 16:47:17
     * update_at: 2023-09-22 16:47:17
     */
    private $ins = null;

    /**
     * file resource handle
     *
     * @var null
     * create_at: 2023-09-22 17:07:03
     * update_at: 2023-09-22 17:07:03
     */
    private $handle = null;

    /**
     * 导出文件名
     *
     * @var null
     * create_at: 2023-09-22 17:29:25
     * update_at: 2023-09-22 17:29:25
     */
    private $fileName = null;

    /**
     * 导出文件保存到服务器路径
     *
     * @var null
     * create_at: 2023-09-22 17:30:54
     * update_at: 2023-09-22 17:30:54
     */
    private $filePath = null;

    /**
     * constructor.
     */
    public function __construct($config = [])
    {
        // 默认配置
        $default = ['path' => storage_path('app/excel')];
        $this->ins = new Excel(array_merge($default, $config));
    }

    /**
     * 获取 file resource handle
     *
     * @return null
     * create_at: 2023-09-22 17:19:06
     * update_at: 2023-09-22 17:19:06
     */
    public function getHandle()
    {
        return $this->handle;
    }

    /**
     * 设置导出文件名
     *
     * @param $fileName
     * @throws Exception
     * create_at: 2023-09-22 17:04:08
     * update_at: 2023-09-22 17:04:08
     */
    public function setFileName($fileName)
    {
        if (empty($fileName)) {
            throw new Exception("未知的导出文件名");
        }

        // 第三个参数 False 暂默认关闭 ZIP64
        $this->fileName = $fileName;
        $fileObject = $this->ins->constMemory($fileName, NULL, false);
        $this->handle = $fileObject->getHandle();
    }

    /**
     * 设置表头
     *
     * @param array $header
     * @throws Exception
     * create_at: 2023-09-22 17:24:58
     * update_at: 2023-09-22 17:24:58
     */
    public function setHeader(array $header = [])
    {
        if (empty($header)) {
            throw new Exception("未知的表头数据");
        }

        $this->ins->header($header);
    }

    /**
     * 设置表头样式
     *
     * create_at: 2023-09-23 14:46:17
     * update_at: 2023-09-23 14:46:17
     */
    public function setHeaderStyle($headerRows = 1)
    {
        if ($headerRows < 1) {
            return;
        }

        $format = new Format($this->handle);

        // 是否简单表头
        $simpleHeader = 1 == $headerRows;

        $fontColor = $simpleHeader ? Format::COLOR_WHITE : Format::COLOR_BLACK;

        // 表头样式
        $headerStyle =
            $format
                ->fontSize(12) // 字号
                ->fontColor($fontColor) // 字体颜色
                ->bold() // 粗体
                ->align(Format::FORMAT_ALIGN_CENTER, Format::FORMAT_ALIGN_VERTICAL_CENTER) // 居中
                ->background(0x409EFF) // 背景色
                ->toResource();

        if ($simpleHeader) {
            $this->ins->setRow("A1", 20, $headerStyle);
        }
    }

    /**
     * 填充数据
     *
     * @param array $data
     * create_at: 2023-09-22 17:25:27
     * update_at: 2023-09-22 17:25:27
     */
    public function setData(array $data = [])
    {
        $this->ins->data([
            $data
        ]);
    }

    /**
     * 导出文件保存到服务器
     *
     * create_at: 2023-09-22 17:26:45
     * update_at: 2023-09-22 17:26:45
     */
    public function output()
    {
        $this->filePath = $this->ins->output();
    }

    /**
     * 导出文件输出到缓冲区
     *
     * create_at: 2023-09-22 17:28:33
     * update_at: 2023-09-22 17:28:33
     */
    public function download()
    {
        $origin = request()->server('HTTP_ORIGIN') ? request()->server('HTTP_ORIGIN') : '';

        $allow = env('COS_ALLOWED_ORIGINS') ? explode(',', env('COS_ALLOWED_ORIGINS')) : [];

        if (!in_array($origin, $allow)) {
            throw new Exception("不支持的请求来源");
        }

        // Set Header
        header("Access-Control-Allow-Origin: {$origin}");
        header("Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        header('Content-Disposition: attachment;filename="' . urlencode($this->fileName) . '"');
        header('Content-Length: ' . filesize($this->filePath));
        header('Content-Transfer-Encoding: binary');
        header('Cache-Control: must-revalidate');
        header('Cache-Control: max-age=0');
        header('Pragma: public');
        header('Access-Control-Expose-Headers: Content-Disposition');

        ob_clean();
        flush();

        if (copy($this->filePath, 'php://output') === false) {
            // Throw exception
            throw new Exception("下载异常");
        }

        // Delete temporary file
        @unlink($this->filePath);
        exit();
    }

    /**
     * 读取文件
     *
     * @param $filePath
     * create_at: 2023-10-05 09:32:35
     * update_at: 2023-10-05 09:32:35
     */
    public function openFile($filePath)
    {
        $this->ins->openFile($filePath);
    }

    /**
     * 读取表
     *
     * @param $sheetIndex
     * create_at: 2023-10-05 09:32:35
     * update_at: 2023-10-05 09:32:35
     */
    public function openSheet()
    {
        $this->ins->openSheet();
    }

    /**
     * 读取全量数据
     *
     * @return array
     * create_at: 2023-10-05 15:54:41
     * update_at: 2023-10-05 15:54:41
     */
    public function getSheetData()
    {
        return $this->ins->getSheetData();
    }

    /**
     * 读取行
     *
     * create_at: 2023-10-05 09:32:35
     * update_at: 2023-10-05 09:32:35
     */
    public function nextRow(?array $dataType = [])
    {
        return $this->ins->nextRow($dataType);
    }

    /**
     * 销毁
     *
     * create_at: 2023-09-23 15:59:51
     * update_at: 2023-09-23 15:59:51
     */
    public function close()
    {
        $this->ins->close();
    }
}
